[XEN] Do not steal work from idle CPUs. This can happen
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 14 Sep 2006 15:01:46 +0000 (16:01 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 14 Sep 2006 15:01:46 +0000 (16:01 +0100)
if a idle CPU is in the process of waking up.
This fix suggested by Anthony Xu <anthony.xu@intel.com> as
it can have a significant boost to HVM performance.
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/common/sched_credit.c

index d183f2dafa2c772c7611aff71980f8440b536833..346554208393dafd1ab23deddd32f37f8a859937 100644 (file)
@@ -987,35 +987,37 @@ csched_load_balance(int cpu, struct csched_vcpu *snext)
          * cause a deadlock if the peer CPU is also load balancing and trying
          * to lock this CPU.
          */
-        if ( spin_trylock(&per_cpu(schedule_data, peer_cpu).schedule_lock) )
+        if ( !spin_trylock(&per_cpu(schedule_data, peer_cpu).schedule_lock) )
         {
+            CSCHED_STAT_CRANK(steal_trylock_failed);
+            continue;
+        }
 
-            spc = CSCHED_PCPU(peer_cpu);
-            if ( unlikely(spc == NULL) )
-            {
-                CSCHED_STAT_CRANK(steal_peer_down);
-                speer = NULL;
-            }
-            else
-            {
-                speer = csched_runq_steal(spc, cpu, snext->pri);
-            }
-
-            spin_unlock(&per_cpu(schedule_data, peer_cpu).schedule_lock);
-
-            /* Got one! */
-            if ( speer )
-            {
-                CSCHED_STAT_CRANK(vcpu_migrate);
-                return speer;
-            }
+        spc = CSCHED_PCPU(peer_cpu);
+        if ( unlikely(spc == NULL) )
+        {
+            CSCHED_STAT_CRANK(steal_peer_down);
+            speer = NULL;
+        }
+        else if ( is_idle_vcpu(per_cpu(schedule_data, peer_cpu).curr) )
+        {
+            speer = NULL;
         }
         else
         {
-            CSCHED_STAT_CRANK(steal_trylock_failed);
+            /* Try to steal work from an online non-idle CPU. */
+            speer = csched_runq_steal(spc, cpu, snext->pri);
         }
-    }
 
+        spin_unlock(&per_cpu(schedule_data, peer_cpu).schedule_lock);
+
+        /* Got one? */
+        if ( speer )
+        {
+            CSCHED_STAT_CRANK(vcpu_migrate);
+            return speer;
+        }
+    }
 
     /* Failed to find more important work */
     __runq_remove(snext);